/**
 * Copyright (C) 2008+ Spark Zheng
 *
 * @file	include/hash.h
 * @brief       A collection of string-key hash functions.
 *
 * @see		dlib
 * @history
 *	version 0.1.0, Spark init hash module
 */

#ifndef _DLIB_HASH_H
#define _DLIB_HASH_H

#ifdef __cplusplus
extern "C" {
#endif

#include "global.h"

#define HASH_SIZE(n)		((uint32_t)1 << (n))
#define HASH_MARK(n)		(HASH_SIZE(n) - 1)

#define HASH_ROTATE32(x, k)	(((x) << (k)) | ((x) >> (32 - (k))))
#define HASH_MIX32(a, b, c)	do { \
	  a -= c; a ^= HASH_ROTATE32(c, 4);  c += b; \
	  b -= a; b ^= HASH_ROTATE32(a, 6);  a += c; \
	  c -= b; c ^= HASH_ROTATE32(b, 8);  b += a; \
	  a -= c; a ^= HASH_ROTATE32(c, 16); c += b; \
	  b -= a; b ^= HASH_ROTATE32(a, 19); a += c; \
	  c -= b; c ^= HASH_ROTATE32(b, 4);  b += a; } while (0)
#define HASH_FINAL32(a, b, c)	do { \
	  c ^= b; c -= HASH_ROTATE32(b, 14); \
	  a ^= c; a -= HASH_ROTATE32(c, 11); \
	  b ^= a; b -= HASH_ROTATE32(a, 25); \
	  c ^= b; c -= HASH_ROTATE32(b, 16); \
	  a ^= c; a -= HASH_ROTATE32(c, 4);  \
	  b ^= a; b -= HASH_ROTATE32(a, 14); \
	  c ^= b; c -= HASH_ROTATE32(b, 24); } while (0)


/**
 * simple_hash
 * @brief A hash algorithm implement.
 * @param key: the key word which need to be hashed.
 * @param key_len: key word length
 */
extern uint32_t simple_hash(const void* key, int key_len);

/**
 * one_at_a_time_hash
 * @brief A hash algorithm implement.
 * @param key: the key word which need to be hashed.
 * @param key_len: key word length
 */
extern uint32_t one_at_a_time_hash(const char *key, uint32_t key_len);

/**
 * elf_hash
 * @brief A hash algorithm implement.
 * @param key: the key word which need to be hashed.
 * @param key_len: key word length
 */
extern uint32_t elf_hash(const char *key, uint32_t key_len);

/* 
 * ext_dx_hack_hash
 * @brief ext2/3/4 filesystem legacy dir hash function
 * @param name: dir name
 * @param len: dir-string length
 */
extern uint32_t ext_dx_hack_hash (const char *k, int len);

/*
 * glib_string_hash
 * @brief A hash algorithm implement.
 * @param key: the key word which need to be hashed.
 */
extern uint32_t glib_string_hash (const void *key);
/**
 * glib_pointer_hash
 * @brief A hash algorithm implement.
 * @param key: the key word which need to be hashed.
 */
extern unsigned long glib_pointer_hash(const void *ptr);

/** 
 * rs_hash
 * @brief A hash algorithm implement.
 * @param key: the key word which need to be hashed.
 * @param key_len: key word length
 */
extern uint32_t rs_hash(const void *key, int key_len);

/** 
 * js_hash
 * @brief A hash algorithm implement.
 * @param key: the key word which need to be hashed.
 * @param key_len: key word length
 */
extern uint32_t js_hash(const void *key, int key_len);

/**
 * sdbm_hash
 * @brief A hash algorithm implement.
 * @param key: the key word which need to be hashed.
 */
extern uint32_t sdbm_hash(const void *key);

/** 
 * bkdr_hash
 * @brief A hash algorithm implement.
 * @param key: the key word which need to be hashed.
 * @param key_len: key word length
 */
extern uint32_t bkdr_hash(const void *key, int key_len);

/**
 * djb_hash
 * @brief A hash algorithm implement.
 * @param key: the key word which need to be hashed.
 */
extern uint32_t djb_hash(const void *key);

/**
 * r5_hash
 * @brief A hash algorithm implement.
 * @param key: the key word which need to be hashed.
 */
extern uint32_t r5_hash(const void *key);

/** 
 * ap_hash
 * @brief A hash algorithm implement.
 * @param key: the key word which need to be hashed.
 * @param key_len: key word length
 */
extern uint32_t ap_hash(const void *key, int key_len);

/** 
 * calc_hash
 * @brief A hash algorithm implement.
 * @param key: the key word which need to be hashed.
 * @param key_len: key word length
 */
extern uint32_t calc_hash(const void* key, int key_len);

/**
 * perfect_word_hash
 * @brief perfect-hash: lookup3.c, by Bob Jenkins, May 2006, Public Domain.
 * @param k: the key, an array of uint32_t values
 * @param length: the length of the key, in uint32_ts
 * @param initval: the previous hash, or an arbitrary value
 */
extern uint32_t perfect_word_hash(const uint32_t *k, uint32_t length,
				  uint32_t initval);

/**
 * perfect_word2_hash
 * @brief perfect-hash: lookup3.c, by Bob Jenkins, May 2006, Public Domain.
 * @param k: the key, an array of uint32_t values
 * @param length: the length of the key, in uint32_ts
 * @param pc[IN]: seed OUT: primary hash value
 * @param pb[IN]: more seed OUT: secondary hash value
 */
extern void perfect_word2_hash(const uint32_t *k, uint32_t length,
			uint32_t *pc, uint32_t *pb);

/**
 * perfect_hash
 * @brief perfect-hash: lookup3.c, by Bob Jenkins, May 2006, Public Domain.
 * @param k: the key (the unaligned variable-length array of bytes)
 * @param length: the length of the key, counting by bytes
 * @param initval: can be any 4-byte value
 */
extern uint32_t perfect_hash(const void *key, uint32_t length,
			     uint32_t initval);

/**
 * perfect2_hash
 * @brief perfect-hash: lookup3.c, by Bob Jenkins, May 2006, Public Domain.
 * @param key: the key to hash
 * @param length: length of the key
 * @param pc: IN: primary initval, OUT: primary hash
 * @param pb: IN: secondary initval, OUT: secondary hash
 */
extern void perfect2_hash(const void *key, uint32_t length,
			  uint32_t *pc, uint32_t *pb);

#ifdef __cplusplus
}
#endif
#endif
